package com.xu.controller;

import com.xu.pojo.Users;
import com.xu.pojo.bo.ShopcartBO;
import com.xu.pojo.bo.UserBO;
import com.xu.service.UserService;
import com.xu.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @author anan
 * @create 2022-01-11 15:27
 */

@RestController
@RequestMapping("passport")
@Api(value = "注册登录", tags = "用于注册登录的相关接口")
public class PassportController extends BaseController{
    @Autowired
    private UserService userService;

    @Autowired
    private RedisOperator redisOperator;

    @ApiOperation(value = "用户名是否存在", notes = "用户名是否存在", httpMethod = "GET")
    @GetMapping("/usernameIsExist")
    public JSONResult userNameIsExist(@RequestParam String username){
        if(StringUtils.isBlank(username)){
            return JSONResult.errorMsg("用户名不能为空");
        }
        if(userService.queryUserIsExists(username)){
            return JSONResult.errorMsg("用户名已经存在");
        }
        else return JSONResult.ok();
    }
    @ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
    @PostMapping("/regist")
    public JSONResult regist(@RequestBody UserBO userBO,
                             HttpServletRequest request,
                             HttpServletResponse response){
        String userName = userBO.getUsername();
        String passWord = userBO.getPassword();
        String confirmPassword = userBO.getconfirmPassword();

        //1、验证三条是否为空
        if(StringUtils.isBlank(userName) || StringUtils.isBlank(passWord) || StringUtils.isBlank(confirmPassword)){
            return JSONResult.errorMsg("用户名或密码不能为空");
        }
        //2、查询用户名是否存在
        if(userService.queryUserIsExists(userName)){
            return JSONResult.errorMsg("用户名已经存在");
        }
        //3、判断密码长度是否小于6
        if(passWord.length() < 6){
            return JSONResult.errorMsg("密码长度不可以小于6");
        }
        //4、判断两次密码是否一致
        if(!passWord.equals(confirmPassword)){
            return JSONResult.errorMsg("两次密码不一致");
        }

        //5、进行注册
        Users userRes = userService.createUser(userBO);
        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(userRes), true);
        synchShopcartData(userRes.getId(), request, response);
        //生成用户token, 存入redis会话
        //同步购物车数据

        return JSONResult.ok(userRes);
    }




    @ApiOperation(value = "用户登录", notes = "用户登录", httpMethod = "POST")
    @PostMapping("/login")
    public JSONResult login(@RequestBody UserBO userBO,
                            HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        String username = userBO.getUsername();
        String password = userBO.getPassword();
        if(StringUtils.isBlank(username) || StringUtils.isBlank(password)) return JSONResult.errorMsg("用户名或密码不能为空");
        Users userRes = userService.queryUserForLogin(username, MD5Utils.getMD5Str(password));
        if(userRes == null) return JSONResult.errorMsg("用户名或密码不正确");

        //将用户信息转为cookie
        userRes = setUsersNull(userRes);
        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(userRes), true);

        synchShopcartData(userRes.getId(), request, response);
        //生成用户token, 存入redis会话
        //同步购物车数据
        return JSONResult.ok(userRes);
    }

    private void synchShopcartData(String userId, HttpServletRequest request,
                                   HttpServletResponse response) {

        /**
         * 1. redis中无数据，如果cookie中的购物车为空，那么这个时候不做任何处理
         *                 如果cookie中的购物车不为空，此时直接放入redis中
         * 2. redis中有数据，如果cookie中的购物车为空，那么直接把redis的购物车覆盖本地cookie
         *                 如果cookie中的购物车不为空，
         *                      如果cookie中的某个商品在redis中存在，
         *                      则以cookie为主，删除redis中的，
         *                      把cookie中的商品直接覆盖redis中（参考京东）
         * 3. 同步到redis中去了以后，覆盖本地cookie购物车的数据，保证本地购物车的数据是同步最新的
         */

        // 从redis中获取购物车
        String shopcartJsonRedis = redisOperator.get(FOODIE_SHOPCART + ":" + userId);

        // 从cookie中获取购物车
        String shopcartStrCookie = CookieUtils.getCookieValue(request, FOODIE_SHOPCART, true);

        if (StringUtils.isBlank(shopcartJsonRedis)) {
            // redis为空，cookie不为空，直接把cookie中的数据放入redis
            if (StringUtils.isNotBlank(shopcartStrCookie)) {
                redisOperator.set(FOODIE_SHOPCART + ":" + userId, shopcartStrCookie);
            }
        } else {
            // redis不为空，cookie不为空，合并cookie和redis中购物车的商品数据（同一商品则覆盖redis）
            if (StringUtils.isNotBlank(shopcartStrCookie)) {

                /**
                 * 1. 已经存在的，把cookie中对应的数量，覆盖redis（参考京东）
                 * 2. 该项商品标记为待删除，统一放入一个待删除的list
                 * 3. 从cookie中清理所有的待删除list
                 * 4. 合并redis和cookie中的数据
                 * 5. 更新到redis和cookie中
                 */

                List<ShopcartBO> shopcartListRedis = JsonUtils.jsonToList(shopcartJsonRedis, ShopcartBO.class);
                List<ShopcartBO> shopcartListCookie = JsonUtils.jsonToList(shopcartStrCookie, ShopcartBO.class);

                // 定义一个待删除list
                List<ShopcartBO> pendingDeleteList = new ArrayList<>();

                for (ShopcartBO redisShopcart : shopcartListRedis) {
                    String redisSpecId = redisShopcart.getSpecId();

                    for (ShopcartBO cookieShopcart : shopcartListCookie) {
                        String cookieSpecId = cookieShopcart.getSpecId();

                        if (redisSpecId.equals(cookieSpecId)) {
                            // 覆盖购买数量，不累加，参考京东
                            redisShopcart.setBuyCounts(cookieShopcart.getBuyCounts());
                            // 把cookieShopcart放入待删除列表，用于最后的删除与合并
                            pendingDeleteList.add(cookieShopcart);
                        }

                    }
                }

                // 从现有cookie中删除对应的覆盖过的商品数据
                shopcartListCookie.removeAll(pendingDeleteList);

                // 合并两个list
                shopcartListRedis.addAll(shopcartListCookie);
                // 更新到redis和cookie
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, JsonUtils.objectToJson(shopcartListRedis), true);
                redisOperator.set(FOODIE_SHOPCART + ":" + userId, JsonUtils.objectToJson(shopcartListRedis));
            } else {
                // redis不为空，cookie为空，直接把redis覆盖cookie
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, shopcartJsonRedis, true);
            }

        }
    }

    private Users setUsersNull(Users userRes){
        userRes.setPassword(null);
        userRes.setUpdatedTime(null);
        userRes.setCreatedTime(null);
        userRes.setBirthday(null);
        userRes.setEmail(null);
        userRes.setMobile(null);
        userRes.setRealname(null);
        return userRes;
    }
    @ApiOperation(value = "用户退出", notes = "用户退出", httpMethod = "POST")
    @PostMapping("/logout")
    public JSONResult logout(@RequestParam String userId,
                             HttpServletRequest request,
                             HttpServletResponse response){
        CookieUtils.deleteCookie(request, response, "user");
        // 用户退出登录，需要清空购物车
        // 分布式会话中需要清除用户数据
        CookieUtils.deleteCookie(request, response, FOODIE_SHOPCART);
        return JSONResult.ok();
    }
}
